Google Cloud PlatformリソースをCDK for Terraformでデプロイしてみた
CX事業部Delivery部の新澤です。
Google Cloud Platform(GCP)のリソースをデプロイするために、CDK for Terraform(CDKTF)を試してみました。
もちろんTerraform単体でもリソースの管理・デプロイは可能なのですが、書き慣れた開発言語でリソースを定義できるのはHCLに不慣れな自分にはかなり魅力的です。
今回は、初期セットアップとシンプルなCDKスタックを作成して、デプロイを試してみます。
検証環境
OS: Debian Linux 11 (VSCode DevContainersのNode.js & TypeScriptを利用)
言語: TypeScript
gcloud CLIのインストール・設定
まずGCPのCLIを利用できるようにします。
インストール
公式ドキュメントの手順にしたがってインストールします。
gcloud CLIの配布URLをパッケージソースに追加します。
$ echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main
Google Cloudの公開鍵をインポートします。
$ curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key --keyring /usr/share/keyrings/cloud.google.gpg add -
gcloud CLIをインストールします。
$ sudo apt-get update && sudo apt-get install google-cloud-cli
確認してみます。
$ gcloud --version Google Cloud SDK 443.0.0 alpha 2023.08.11 beta 2023.08.11 bq 2.0.96 bundled-python3-unix 3.9.16 core 2023.08.11 gcloud-crc32c 1.0.0 gsutil 5.25
大丈夫そうですね。
初期化
gcloud CLIの初期化を行います。
$ gcloud init Welcome! This command will take you through the configuration of gcloud. Your current configuration has been set to: [default] You can skip diagnostics next time by using the following flag: gcloud init --skip-diagnostics Network diagnostic detects and fixes local network connection issues. Checking network connection...done. Reachability Check passed. Network diagnostic passed (1/1 checks passed). You must log in to continue. Would you like to log in (Y/n)? y Go to the following link in your browser: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=32555940559.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fsdk.cloud.google.com%2Fauthcode.html&scope=openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fappengine.admin+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fsqlservice.login+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcompute+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Faccounts.reauth&state=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&prompt=consent&access_type=offline&code_challenge=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&code_challenge_method=S256
GCPにログインするためのURLが表示されるので、ブラウザでアクセスし、認証後に表示される認証コードを入力します。
Enter authorization code: <ブラウザで認証後に表示される認証コード> You are logged in as: [xxxxxxxx@hoge.com].
プロジェクトを選択します。
Pick cloud project to use: [1] my-project [2] Enter a project ID [3] Create a new project Please enter numeric choice or text value (must exactly match list item): 1 Your current project has been set to: [my-project].
Terraform CLI
次はTerraform CLIをインストールします。
インストール
PGP署名をインストールします。
$ sudo apt-get update && sudo apt-get install -y gnupg software-properties-common $ wget -O- https://apt.releases.hashicorp.com/gpg | \ gpg --dearmor | \ sudo tee /usr/share/keyrings/hashicorp-archive-keyring.gpg $ gpg --no-default-keyring \ --keyring /usr/share/keyrings/hashicorp-archive-keyring.gpg \ --fingerprint
HashiCorpのリポジトリを追加します。
$ echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] \ https://apt.releases.hashicorp.com $(lsb_release -cs) main" | \ sudo tee /etc/apt/sources.list.d/hashicorp.list
CLIをインストールします。
$ sudo apt update && sudo apt-get install terraform $ terraform --version Terraform v1.5.5 on linux_arm64
CDK for Terraform(CDKTF)
ようやくCDKTFまで辿り着きました。
インストール
CDKTF CLIをインストールします。
$ npm install --global cdktf-cli@latest npm WARN deprecated @npmcli/ci-detect@1.4.0: this package has been deprecated, use `ci-info` instead added 477 packages in 38s 98 packages are looking for funding run `npm fund` for details $ cdktf --version 0.18.0
初期化
CDKTFの初期化を実行して、雛形を作成します。
providerにgoogleを指定すると、GCPのリソースを定義するためのコンストラクトが.genディレクトリに作成されます。
$ cdktf init --template=typescript --providers=google --local Note: By supplying '--local' option you have chosen local storage mode for storing the state of your stack. This means that your Terraform state file will be stored locally on disk in a file 'terraform.<STACK NAME>.tfstate' in the root of your project. ? Project Name cdktf-gcp-sample ? Project Description A simple getting started project for cdktf. ? Do you want to start from an existing Terraform project? no ? Do you want to send crash reports to the CDKTF team? Refer to https://developer.hashicorp.com/terraform/cdktf/create-and-deploy/configuration-file#enable-crash-reporting-for-the-cli for more information no added 2 packages, and audited 57 packages in 3s 7 packages are looking for funding run `npm fund` for details found 0 vulnerabilities added 313 packages, and audited 370 packages in 24s 37 packages are looking for funding run `npm fund` for details found 0 vulnerabilities (略) [2023-08-22T00:54:42.931] [INFO] default - Adding local provider registry.terraform.io/hashicorp/google with version constraint undefined to cdktf.json Local providers have been updated. Running cdktf get to update... Generated typescript constructs in the output directory: .gen
リモートバックエンド用バケットの作成
Terraformを利用する際には、リソースの状態を管理するtfstateファイルを管理する必要があります。
デフォルトではローカルにtfstateファイルが作成されますが、チーム開発の場合はAWS S3やGCP Cloud StorageといったストレージサービスやTerraform Cloudなどのリモートバックエンドと呼ばれる管理方法を選択することが多いです。
ここでは、Cloud Storageでリモートバックエンドを構成してみます。
gcloud CLIでバケットを作成します。
$ gcloud storage buckets create gs://tf-remote-backend-xxxxxxxx Creating gs://tf-remote-backend-xxxxxxxx/... $ gcloud storage ls gs://tf-remote-backend-xxxxxxxx/
CDKの定義
ここではCloud Storageバケットを1つ作成するだけのシンプルなCDKスタックを作成してみます。
以下、全ソースコードです。
import { Construct } from 'constructs'; import { App, GcsBackend, TerraformStack } from 'cdktf'; import * as google from './.gen/providers/google'; class MyStack extends TerraformStack { constructor(scope: Construct, id: string) { super(scope, id); // GCPプロバイダー new google.provider.GoogleProvider(this, 'GoogleProvider', { project: 'my-project', }); // リモートバックエンドをCloud Storageバケットで構成 new GcsBackend(this, { bucket: 'tf-remote-backend-xxxxxxxx', }); // バケット new google.storageBucket.StorageBucket(this, 'StorageBucket', { location: 'us-central1', name: 'mysample-bucket-xxxxxxxx', }); } } const app = new App(); new MyStack(app, 'cdktf-gcp-sample'); app.synth();
GCPリソースを定義するために、CDKTFの初期化時に生成されたGCPコンストラクトを.genディレクトリからインポートします。
import * as google from './.gen/providers/google';
リモートバックエンドに先ほどCLIで作成したバケットを指定します。
new GcsBackend(this, { bucket: 'tf-remote-backend-xxxxxxxx', });
デプロイ
CDKTF CLIで作成したCDKスタックのdiffを実行して、作成されるリソースを確認してみます。
初回実行時にはスタックで定義したリモートバックエンドの初期化も行われます。
$ cdktf diff
このとき以下の認証エラーが発生した場合は、gcloud CLIで認証を行います。
[2023-08-22T01:20:50.335] [ERROR] default - ╷ │ Error: Attempted to load application default credentials since neither `credentials` nor `access_token` was set in the provider block. No credentials loaded. To use your gcloud credentials, run 'gcloud auth application-default login'
以下を実行して、gcloud CLIインストール時と同様に表示された認証URLにアクセスし、認証後に表示される認証コードを入力します。
$ gcloud auth application-default login
再度diffを実行してみます。
$ cdktf diff cdktf-gcp-sample Initializing the backend... cdktf-gcp-sample cdktf-gcp-sample Successfully configured the backend "gcs"! Terraform will automatically use this backend unless the backend configuration changes. cdktf-gcp-sample Initializing provider plugins... - Finding hashicorp/google versions matching "4.79.0"... cdktf-gcp-sample - Installing hashicorp/google v4.79.0... cdktf-gcp-sample - Installed hashicorp/google v4.79.0 (signed by HashiCorp) Terraform has created a lock file .terraform.lock.hcl to record the provider selections it made above. Include this file in your version control repository so that Terraform can guarantee to make the same selections by default when you run "terraform init" in the future. cdktf-gcp-sample Terraform has been successfully initialized! You may now begin working with Terraform. Try running "terraform plan" to see any changes that are required for your infrastructure. All Terraform commands should now work. If you ever set or change modules or backend configuration for Terraform, rerun this command to reinitialize your working directory. If you forget, other commands will detect it and remind you to do so if necessary. cdktf-gcp-sample - Fetching hashicorp/google 4.79.0 for linux_amd64... cdktf-gcp-sample - Retrieved hashicorp/google 4.79.0 for linux_amd64 (signed by HashiCorp) - Obtained hashicorp/google checksums for linux_amd64; Additional checksums for this platform are now tracked in the lock file cdktf-gcp-sample Success! Terraform has updated the lock file. Review the changes in .terraform.lock.hcl and then commit to your version control system to retain the new checksums. cdktf-gcp-sample Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: cdktf-gcp-sample + create Terraform will perform the following actions: # google_storage_bucket.StorageBucket (StorageBucket) will be created + resource "google_storage_bucket" "StorageBucket" { + force_destroy = false + id = (known after apply) + labels = (known after apply) + location = "US-CENTRAL1" + name = "mysample-bucket-xxxxxxxx" + project = (known after apply) + public_access_prevention = (known after apply) + self_link = (known after apply) + storage_class = "STANDARD" + uniform_bucket_level_access = (known after apply) + url = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. ───────────────────────────────────────────────────────────────────────────── Saved the plan to: plan To perform exactly these actions, run the following command to apply: terraform apply "plan"
問題なくdiffが表示されたら、デプロイしてみます。
$ cdktf deploy cdktf-gcp-sample Initializing the backend... cdktf-gcp-sample Initializing provider plugins... - Reusing previous version of hashicorp/google from the dependency lock file cdktf-gcp-sample - Using previously-installed hashicorp/google v4.79.0 Terraform has been successfully initialized! (略) cdktf-gcp-sample google_storage_bucket.StorageBucket (StorageBucket): Creating... cdktf-gcp-sample google_storage_bucket.StorageBucket (StorageBucket): Creation complete after 3s [id=mysample-bucket-xxxxxxxx] cdktf-gcp-sample Apply complete! Resources: 1 added, 0 changed, 0 destroyed. No outputs found. $ gcloud storage ls gs://mysample-bucket-xxxxxxxx/ gs://tf-remote-backend-xxxxxxxx/
スタックで定義したバケットが作成されました!
後片付け
スタックを削除します。
$ cdktf destroy
最後に
GCPを使うのは初めてだったのですが、CDKTFを使って慣れた開発言語で記述できたので、簡単にデプロイを試すことができました。
次はデータベースサービスやコンテナのデプロイを試してみたいと思います。